package com.ht.api.db.event;

import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;

import com.ht.api.db.Db;
import com.ht.api.db.DbConfig;
import com.ht.api.db.DbList;
import com.ht.api.db.Entity;
import com.ht.api.db.bean.Table;
import com.ht.api.db.cache.Cache;
import com.ht.api.db.task.HtTaskExecutor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 数据库操作事件类
 * @author asq
 * @createTime 2025年1月6日 20:08:50
 */
@Slf4j
public class DbEventManager {
	@Autowired
	private static Map<String, Cache> cacheMap = SpringUtil.getBeansOfType(Cache.class);

	/**
	 * 数据库insert事件
	 * @param ds 数据源
	 * @param bean insert的数据
	 */
	public static void onInsert(DataSource ds, Entity bean) {
		// 1.更新缓存
		try {
			// 查找对应表的cache实现类
			Cache cacheHandler = cacheMap.get(String.format("%s_cache", bean.getTable()));
			
			// 如果找到了，则调用refresh方法刷新缓存
			if (cacheHandler != null) {
				cacheHandler.refresh(ds, bean);
			}
		} catch (Exception e) {
			log.error("[DbEventManager]insert刷新缓存时出现异常：{}", e.getMessage(), e);
		}
		
		// 2.级联删除
		try {
			if (bean.containsKey("sys_deleted")) {
				int sys_deleted = bean.getInt("sys_deleted");
				if (sys_deleted == 0) {
					Table table = DbConfig.getTable(bean.getTable());
					if (table != null) {
						String delConfig = table.getDelConfig();
						if (StrUtil.isNotBlank(delConfig)) {
							log.info("[DbEventManager]触发级联删除，原始表：{}", bean.getTable());

							HtTaskExecutor.execute(() -> {
								cascadeDelete(ds, bean, delConfig);
							});
						} else {
							log.info("[DbEventManager]未配置级联删除规则，忽略级联删除，表：{}", bean.getTable());
						}
					} else {
						log.warn("[DbEventManager]缓存中未找到表的元数据配置，忽略级联删除，表：{}", bean.getTable());
					}
				}
			}
			
		} catch (Exception e) {
			log.error("[DbEventManager]级联删除出现异常：{}", e.getMessage(), e);
		}
		
	}

	/**
	 * 执行级联删除，级联删除的配置格式如下：
	 * <pre>
	   	[
			{
				"source_field": "main_id", // 当前表的字段名
				"rel_table": "sys_group",  // 要级联删除的目标表（可以是本表）
				"rel_field": "parent_id"   // 目标表中的关联字段
			}
		]
		</pre>
	 * @param ds 数据源
	 * @param bean 删除事件的原始数据Entity
	 * @param delConfig 原始数据Entity的级联删除规则
	 */
	private static void cascadeDelete(DataSource ds, Entity bean, String delConfig) {
		JSONArray configArr = JSONUtil.parseArray(delConfig);
		for (int i = 0; i < configArr.size(); i++) {
			JSONObject config = configArr.getJSONObject(i);
			String sourceField = config.getStr("source_field");
			String relTable = config.getStr("rel_table");
			String relField = config.getStr("rel_field");
			
			// 找出配置规则中原始数据Bean的外键值
			String sourceFieldVal = bean.getMainId();
			if (!"main_id".equals(sourceField)) {
				String sql = String.format("select * from %s where main_id=?", bean.getTable());
				Entity sourceBean = Db.findOne(ds, sql, bean.getMainId());
				if (sourceBean == null) {
					log.warn("[DbEventManager]原始数据已不存在，忽略级联删除，原始表：{}，目标表：{}，main_id：{}", 
							bean.getTable(), relTable, bean.getMainId());
					continue;
				}
				sourceFieldVal = sourceBean.getStr(sourceField);
			}
			
			// 根据配置，查询出需要级联删除的数据列表
			DbList list = Db.createSqlParser(relTable).where(relField, sourceFieldVal).query(ds);
			
			// 批量删除
			if (!list.isEmpty()) {
				list.stream().forEach(b -> b.set("sys_deleted", 0));
				Db.insertBatch(ds, list, false);
				log.info("[DbEventManager]级联删除成功，原始表：{}，目标表：{}，删除数据条数：{}", bean.getTable(), relTable, list.size());
			}
		}
	}

}
